﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text; 
using La.Code.SocketUtil;


namespace LiAnProxy
{
    /// <summary>
    /// Socket代理
    /// </summary>
    public class ProxyHttp
    {
        /// <summary>
        /// 异常日志 委托
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="content"></param>
        /// <param Name="ex"></param>
        public delegate void ErrorLogEventHandler(IDataTransmit sender, string content, Exception ex);
        /// <summary>
        /// 错误日志 事件
        /// </summary>
        public event ErrorLogEventHandler WriteErrorLogEvent;
        /// <summary>
        /// 
        /// </summary>
        public TcpService Server;
        /// <summary>
        /// 代理对象
        /// </summary>
        public ProxyModel SocketModel { get; set; }

        public ProxyHttp(ProxyModel socketModel)
            : this(socketModel, 1000)
        {
        }
        public ProxyHttp(ProxyModel socketModel, int proxyMax)
        {
            socketModel.ProxyType = ProxyType.Http;
            socketModel.ProxyMax = proxyMax;
            //在指定端口上建立监听线程
            Server = new TcpService(socketModel.ProxyPort, socketModel.ProxyMax, socketModel.ProxyIp);
            Server.Connected += server_Connected;
            Server.DisConnect += server_DisConnect;
            //启动服务
            Server.Start();
        }
        /// <summary>
        /// 
        /// </summary> 
        /// <param name="proxyPort">代理端口</param>
        /// <param name="targetIp">目标地址</param>
        /// <param name="targetPort">目标端口</param> 
        public ProxyHttp(int proxyPort, string targetIp, int targetPort)
            : this("0.0.0.0", proxyPort, targetIp, targetPort)
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="proxyIp">代理地址</param> 
        /// <param name="proxyPort">代理端口</param>
        /// <param name="targetIp">目标地址</param>
        /// <param name="targetPort">目标端口</param> 
        public ProxyHttp(string proxyIp, int proxyPort, string targetIp, int targetPort)
            : this(proxyIp, 1000, proxyPort, targetIp, targetPort, 60)
        {

        }
        /// <summary>
        /// 
        /// </summary> 
        /// <param name="proxyMax">代理服务的最大数量</param>
        /// <param name="proxyPort">代理端口</param>
        /// <param name="targetIp">目标地址</param>
        /// <param name="targetPort">目标端口</param>
        /// <param name="targetTimeOut">超时时间</param>
        public ProxyHttp(int proxyPort, int proxyMax, string targetIp, int targetPort, int targetTimeOut)
            : this("0.0.0.0", proxyMax, proxyPort, targetIp, targetPort, targetTimeOut)
        {
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="proxyIp">代理地址</param>
        /// <param name="proxyMax">代理服务的最大数量</param>
        /// <param name="proxyPort">代理端口</param>
        /// <param name="targetIp">目标地址</param>
        /// <param name="targetPort">目标端口</param>
        /// <param name="targetTimeOut">超时时间</param>
        public ProxyHttp(string proxyIp, int proxyMax, int proxyPort, string targetIp, int targetPort, int targetTimeOut)
        {
            try
            {
                SocketModel = new ProxyModel
                {
                    ProxyType = ProxyType.Http,
                    TargetIp = targetIp,
                    TargetPort = targetPort,
                    TargetTimeOut = targetTimeOut,
                    ProxyIp = proxyIp,
                    ProxyPort = proxyPort,
                    ProxyMax = proxyMax
                };
                //在指定端口上建立监听线程
                Server = new TcpService(SocketModel.ProxyPort, SocketModel.ProxyMax, SocketModel.ProxyIp);
                Server.Connected += server_Connected;
                Server.DisConnect += server_DisConnect;


            }
            catch (Exception ex)
            {
                WriteErrorLogEvent(null, "连接处理", ex);
            }
        }

        public void Start()
        {
            //启动服务
            Server.Start();
        }

        public void Stop()
        {
            Server.Stop();
        }

        /// <summary>
        /// 连接处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void server_Connected(IDataTransmit sender, NetEventArgs e)
        {
            try
            {
                //接受委托
                sender.ReceiveData += sender_ReceiveData;
                //接收数据
                sender.Start();
            }
            catch (Exception ex)
            {
                WriteErrorLogEvent(sender, "连接处理", ex);
            }
        }
        /// <summary>
        /// 接受处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void sender_ReceiveData(IDataTransmit sender, NetEventArgs e)
        {
            try
            {
                Encoding encoding = Encoding.GetEncoding("utf-8");
                //接受请求数据
                byte[] data = (byte[])e.EventArg;

                string temp = encoding.GetString(data, 0, data.Length);
                Write("接收：" + temp);


                string[] head = temp.Substring(0, temp.IndexOf("*/*", StringComparison.Ordinal)).Split(' ');
                string[] content = temp.Substring(temp.IndexOf("*/*", StringComparison.Ordinal) + 3, temp.Length - temp.IndexOf("*/*", StringComparison.Ordinal) - 3).Replace("\r\n", "|").Split('|');


                //HttpHelper http = new HttpHelper();
                ////创建Httphelper参数对象
                //HttpItem item = new HttpItem()
                //{
                //    Method = head[0],
                //    URL = head[1],
                //    ContentType = content[1].Split(':')[1] //"text/html; charset=gbk",//返回类型    可选项有默认值 

                //};


                ////请求的返回值对象
                //HttpResult result = http.GetHtml(item);
                //WebHeaderCollection ad= result.Header;
                ////获取请请求的Html
                //string html = result.Html;

                ////返回结果
                //sender.Send(result.Header+html);

                string[] urlTemp = head[1].Substring(head[1].IndexOf("//", StringComparison.Ordinal) + 2, head[1].Length - head[1].IndexOf("//", StringComparison.Ordinal) - 2).Split(':');
                urlTemp[0] = urlTemp[0].Replace('/', ' ').Trim();
                IPEndPoint ipEndpoint;
                IPAddress ip;
                //  
                if (urlTemp.Length > 1)
                { //IP地址加端口
                    IPAddress.TryParse(urlTemp[1], out ip);
                    ipEndpoint = new IPEndPoint(ip, Int32.Parse(urlTemp[1]));

                }
                else
                {
                    //通过域名解析IP
#pragma warning disable 618
                    IPHostEntry ipHost = Dns.Resolve(urlTemp[0]);
#pragma warning restore 618
                    Write("远程主机名： " + ipHost.HostName);
                    IPAddress[] address = ipHost.AddressList;
                    Write("Web服务器IP地址：" + address[0]);
                    ipEndpoint = new IPEndPoint(address[0], 80);
                }

                //得到编码格式
                if (temp.IndexOf("charset") > -1)
                {
                    string charset =
                        temp.Substring(temp.IndexOf("charset"),
                            temp.LastIndexOf("\r\n") - temp.IndexOf("charset"))
                            .Substring(0,
                                temp.Substring(temp.IndexOf("charset"),
                                    temp.LastIndexOf("\r\n") - temp.IndexOf("charset")).IndexOf("\r\n"));

                    //  utf-8,gbk,gb2312 
                    string code = charset.Substring(charset.IndexOf('=') + 1, charset.Length - charset.IndexOf('=') - 1);
                    encoding = Encoding.GetEncoding(code);
                }

                //解析出要访问的服务器地址

                Socket psocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //创建连接Web服务器端的Socket对象
                psocket.Connect(ipEndpoint);
                //Socket连Web接服务器
                if (psocket.Connected)
                    Write("Socket 正确连接！");
                string get = temp;
                Byte[] byteGet = _ascii.GetBytes(get);
                psocket.Send(byteGet, byteGet.Length, 0);
                //代理访问软件对服务器端传送HTTP请求命令



              
                //int rBytes = psocket.Receive(recvBytes, recvBytes.Length, SocketFlags.None);
                int rBytes = 1024*40;
                //代理访问软件接收来自Web服务器端的反馈信息
                Write("接收字节数：" + rBytes);
                String strRetPage = "";
              //  int i = 0;
                //while (rBytes == 1024 * 40)
                //{
                //    Byte[] recvBytes = new Byte[rBytes];
                //    //rBytes = psocket.Receive(recvBytes, rBytes, SocketFlags.None); 
                //    rBytes = psocket.Receive(recvBytes);
                //    strRetPage = strRetPage + encoding.GetString(recvBytes, 0, rBytes);
                //    i++;
                //    if (i > 15)
                //    {
                //        string d = "";
                //    }

                //}
                //if (rBytes > 0)
                //{
                //    Byte[] recvBytes1 = new Byte[rBytes];
                //    psocket.Receive(recvBytes1);
                //   // rBytes = psocket.Receive(recvBytes1, recvBytes1.Length, SocketFlags.None);
                //    strRetPage = strRetPage + encoding.GetString(recvBytes1, 0, rBytes);
                //}

                int length = 0;
                byte[] buffer = new byte[1024];
                List<byte> data1 = new List<byte>();
                while ((length = psocket.Receive(buffer)) > 0)
                {
                    for (int j = 0; j < length; j++)
                    {
                        data1.Add(buffer[j]);
                    }
                    if (length < buffer.Length)
                    {
                        break;
                    }
                }
                strRetPage = strRetPage + encoding.GetString(data1.ToArray(), 0, data1.ToArray().Length);
                psocket.Shutdown(SocketShutdown.Both);
                psocket.Close();

                sender.Send(strRetPage);
                //SendMessage(sender.TcpSocket, strRetPage, encoding);
                sender.TcpSocket.Close();

            }
            catch (Exception ex)
            {
                WriteErrorLogEvent(sender, "接受处理", ex);
            }
        }

        readonly Encoding _ascii = Encoding.ASCII;

        //传送从Web服务器反馈的数据到客户端
        private void SendMessage(Socket s, string message, Encoding encoding)
        {
            //_buffer = new Byte[message.Length + 1];
            //int length = _ascii.GetBytes(message, 0, message.Length, _buffer, 0);

            Byte[] _buffer; _buffer = encoding.GetBytes(message);
            Write("传送字节数：" + _buffer.Length.ToString());
            s.Send(_buffer, _buffer.Length, 0);

        }

        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void server_DisConnect(IDataTransmit sender, NetEventArgs e)
        {
            try
            {
                //string tempKey = "";


            }
            catch (Exception ex)
            {
                WriteErrorLogEvent(sender, "断开连接", ex);
            }
        }
        void Write(string mes)
        {
            if (ShowMesEvent != null)
                ShowMesEvent(mes, 1);
            //var log = LogFactory.GetLogger(GetType());
            //log.Info(mes);
        }
        /// <summary>
        /// 消息时间
        /// </summary>
        public event ShowMesHandle ShowMesEvent;

    }
}
